今天繼續來完成前端網站 React 的部分,首先有好幾個地方要修正,像是資料呈現的屬性資料顯然是不夠的、圖表上的顯然是庫存而不是價格、每週的銷售紀錄等等呈現。
// types.tsx
export type SaleRecord = {
    week: number;
    price: number;       // 價錢
    initialStock: number; // 存貨,初始的存貨量
    sales: number;      // 銷售,賣出的數量
    remainingStock: number; // 剩餘存貨 = 初始存貨 - 賣出的數量
    revenue: number;    // 營收 = 價錢 x 賣出的數量
    accumulatedRevenue: number; // 累積營收
  };
修正需要呈現的資料屬性。
// components/LineChart.tsx
import React from 'react';
import { Line } from 'react-chartjs-2';
import { SaleRecord } from './types';
import { Chart, registerables } from 'chart.js';
type Props = {
    data: SaleRecord[];
};
const LineChart: React.FC<Props> = ({ data }) => {
  Chart.register(...registerables);
    const chartData = {
        labels: data.map(record => `Week ${record.week}`),
        datasets: [
            {
                label: 'Remaining Stock',
                data: data.map(record => record.remainingStock),
                fill: false,
                backgroundColor: 'rgb(75, 192, 192)',
                borderColor: 'rgba(75, 192, 192, 0.2)',
            },
        ],
    };
    return <Line data={chartData} />;
};
export default LineChart;
大致上修改一下呈現的是剩餘存貨量~
// components/PricingControl.tsx
import React, { useState } from 'react';
type Props = {
    onSelect: (price: number) => void;
};
const PricingControl: React.FC<Props> = ({ onSelect }) => {
    const [selectedPrice, setSelectedPrice] = useState<number | null>(null);
    const prices = [60, 54, 48, 36];
    return (
        <div>
            {prices.map((price) => (
                <button
                    key={price}
                    onClick={() => {
                        setSelectedPrice(price);
                        onSelect(price);
                    }}
                    disabled={selectedPrice !== null && price > selectedPrice}
                >
                    ${price}
                </button>
            ))}
        </div>
    );
};
export default PricingControl;
大概修正一下銷售數字和銷售一但低價賣出,就不能回到高價賣出了。
// logic/salesLogic.ts
export const simulateSales = (remainingStock: number): number => {
    const sales = Math.floor(Math.random() * (120 - 70 + 1) + 70);
    return Math.min(sales, remainingStock);
}
修正一下銷售的隨機,讓他先介於70~120之間,並且不能超過剩餘存貨數量。
// components/SalesTable.tsx
import React from 'react';
import { SaleRecord } from './types';
type Props = {
    data: SaleRecord[];
};
const SalesTable: React.FC<Props> = ({ data }) => {
    return (
        <table>
            <thead>
                <tr>
                    <th>週</th>
                    <th>價格</th>
                    <th>存貨</th>
                    <th>銷售</th>
                    <th>剩餘存貨</th>
                    <th>營收</th>
                    <th>累計營收</th>
                </tr>
            </thead>
            <tbody>
                {data.map(record => (
                    <tr key={record.week}>
                        <td>{record.week}</td>
                        <td>{record.price}</td>
                        <td>{record.initialStock}</td>
                        <td>{record.sales}</td>
                        <td>{record.remainingStock}</td>
                        <td>{record.revenue}</td>
                        <td>{record.accumulatedRevenue}</td>
                    </tr>
                ))}
            </tbody>
        </table>
    );
};
export default SalesTable;
先製作一個簡單的表格呈現,之後再美化。
// App.tsx
import React, { useState } from 'react';
import LineChart from './Component/LineChart';
import PricingControl from './Component/PricingControl';
import { SaleRecord } from './Component/types';
import { simulateSales } from './Component/salesLogic';
import SalesTable from './Component/SalesTable';
const INITIAL_STOCK = 2000;
const App: React.FC = () => {
    const [salesData, setSalesData] = useState<SaleRecord[]>([
        { week: 1, price: 60, initialStock: INITIAL_STOCK, sales: 0, remainingStock: INITIAL_STOCK, revenue: 0, accumulatedRevenue: 0 },
    ]);
    const handlePricingSelect = (price: number) => {
        const currentWeek = salesData.length;
        const previousRecord = salesData[currentWeek - 1];
        const sales = simulateSales(previousRecord.remainingStock);
        const newRemainingStock = previousRecord.remainingStock - sales;
        const revenue = sales * price;
        const accumulatedRevenue = previousRecord.accumulatedRevenue + revenue;
        const record: SaleRecord = {
            week: currentWeek + 1,
            price,
            initialStock: INITIAL_STOCK,
            sales,
            remainingStock: newRemainingStock,
            revenue,
            accumulatedRevenue,
        };
        setSalesData([...salesData, record]);
    };
    return (
        <div className="App">
            <h1>Retail Simulation</h1>
            <PricingControl onSelect={handlePricingSelect} />
            <LineChart data={salesData} />
            <SalesTable data={salesData} />
        </div>
    );
};
export default App;
其中針對 handlePricingSelect 做了點修正,並且新增 <SalesTable data={salesData} /> 的呈現。
今天就先到這裡好了,明天在繼續優化一下。